package cn.com.hhrcw.utils.resume;

import cn.com.hhrcw.area.entity.SysArea;
import cn.com.hhrcw.area.service.ISysAreaService;
import cn.com.hhrcw.entity.*;
import cn.com.hhrcw.service.*;
import cn.com.hhrcw.utils.ProvinceCityCountyUtils;
import cn.com.hhrcw.utils.edu.EduLabelUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.policy.HackLoopTableRenderPolicy;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 生成word版的简历（2022年4月1日10:45:55 zhf 抽离出来，原来所在是ICvResumeService 代码 太长 ）
 * </p>
 *
 * @author jiangdong
 * @since 2020-10-29
 */

@Transactional(rollbackFor = Exception.class)
@Slf4j
@Component
public class ResumeWordUtil {

    @Autowired
    IPiInfoService piInfoService;

    @Autowired
    ICvResumeService cvResumeService;

    @Autowired
    private EduLabelUtil eduLabelUtil;

    @Autowired
    private ICvUserWorkInfoService cvUserWorkInfoService;

    @Autowired
    private ICvProjectInfoService cvProjectInfoService;

    @Autowired
    private ICvUserEduInfoService cvUserEduInfoService;

    @Autowired
    private ICvTrainService cvTrainService;

    @Autowired
    private ICvSkillsService cvSkillsService;

    @Autowired
    private ICvCertificateService cvCertificateService;

    @Autowired
    private IFileService fileService;

    @Autowired
    private ISysBaseAPI sysBaseAPI;

    @Autowired
    private IOpJobService opJobService;

    @Autowired
    private IOpDeliveryHistoryService opDeliveryHistoryService;

    @Autowired
    private ICvFamilyMemberService cvFamilyMemberService;

    @Autowired
    private ISysAreaService sysAreaService;

    @Autowired
    private TransNameUtil transNameUtil;

    public static final String DATE_FORMAT = "yyyy.MM.dd";

    public static final String DATE_MONTH_FORMAT = "yyyy.MM";

    /**
     * 校招简历doc
     *
     * @return
     */
    @SneakyThrows
    public String generateResumeWord(CvResume resume, Integer lanType, String deliverJobId) {
        ZipSecureFile.setMinInflateRatio(0);
        final String[] sex = {"无", "男", "女"};
        final String[][] maritalStatus = {
            {"未婚", "已婚已育", "已婚未育", "离异"},
            {"Unmarried", "Married", "Married", "Divorced"}
        };

        Dict params = Dict.create();
        //2022年4月1日14:06:10 zhf 添加
        String majorWorkPerformance = resume.getMajorWorkPerformance();
        if(StrUtil.isBlank(majorWorkPerformance) || "无".equals(majorWorkPerformance.trim())){
            majorWorkPerformance = "                                      /";
            params.set("majorWorkPerformance",majorWorkPerformance);
        }else {
            params.set("majorWorkPerformance",majorWorkPerformance);
        }

//        params.set("majorWorkPerformance", Texts.of(majorWorkPerformance).style(style).create());

        params.set("adjustFlag", "{{adjustFlag}}");
        params.set("jobName", "{{jobName}}");
        //是否同意调剂
        if (StrUtil.isNotBlank(deliverJobId)) {
            OpJob opJob = this.opJobService.getById(deliverJobId);
            params.set("jobName", opJob.getJobName());
            OpDeliveryHistory history = this.opDeliveryHistoryService.lambdaQuery()
                .eq(OpDeliveryHistory::getJobId, deliverJobId)
                .eq(OpDeliveryHistory::getUserId, resume.getUserId())
                .orderByDesc(OpDeliveryHistory::getCreateTime)
                .last("limit 1")
                .one();
            String adjustFlag = Optional.ofNullable(history).map(OpDeliveryHistory::getR10).map(e -> StrUtil.equals(e, "1") ? "是" : "否").orElse("无");
            //String adjustFlag = "/";
            params.set("adjustFlag", adjustFlag);
        }
        PiInfo piInfo = this.piInfoService.lambdaQuery()
            .eq(PiInfo::getUserId, resume.getUserId())
            .one();
        params.set("name", piInfo.getName());
        params.set("sex", piInfo.getSex() == null ? "无" : sex[piInfo.getSex()]);
        params.set("national", piInfo.getR2());
        params.set("birthday", DateUtil.format(piInfo.getBirthday(), DATE_FORMAT));
        params.set("political", piInfo.getPolitical());
        params.set("partyTime", Optional.ofNullable(DateUtil.format(piInfo.getPartyTime(), DATE_FORMAT)).orElse("无"));
        params.set("maritalStatus", piInfo.getMaritalStatus() == null ? "无" : maritalStatus[resume.getLanType()][piInfo.getMaritalStatus()]);
        params.set("foreignLanguage", piInfo.getForeignLanguage());
        params.set("computerSkill", piInfo.getComputerSkill());

        PiInfo info = piInfo;
        // 民族
        params.put("nation", info.getR2());
        //身高
        params.put("height", StringUtils.isNotBlank(info.getR3()) ? info.getR3() + "CM" : " ");
        //体重
        params.put("weight", StringUtils.isNotBlank(info.getR4()) ? info.getR4() + "Kg" : " ");
        //驾照
        params.put("driver", StringUtils.isNotBlank(info.getR5()) ? info.getR5() : " ");
        //身份证号（小朱用的 蒙圈，虽然word用的是idNumber 但竟然也对  ）
        params.put("idCard", StringUtils.isNotBlank(info.getR6()) ? info.getR6() : " ");
        // 民族
        params.put("workYears", null == info.getWorkYears() ? "无" : info.getWorkYears() + "");

        if (StrUtil.isNotBlank(piInfo.getHomeTown())){
            List<String> homeTown = this.sysAreaService.lambdaQuery()
                .in(SysArea::getId, piInfo.getHomeTown().split(","))
                .list()
                .stream()
                .map(SysArea::getName)
                .collect(Collectors.toList());
            params.set("homeTown", ProvinceCityCountyUtils.getProvinceCityCountyShort(homeTown));
        } else {
            params.set("homeTown", "无");
        }//身份证号
        params.set("idNumber", Optional.ofNullable(piInfo.getIdNumber()).orElse("无"));
        params.set("phone", piInfo.getPhone());
        params.set("email", piInfo.getEmail());
        //紧急联系人
        params.set("urgent", piInfo.getR7());
        log.info("==紧急联系人==" + piInfo.getR7());
        //紧急联系人电话
        params.set("urphone", piInfo.getR8());
        if (StrUtil.isNotBlank(piInfo.getLiveCity())) {
            List<String> liveCity = this.sysAreaService.lambdaQuery()
                .in(SysArea::getId, piInfo.getLiveCity().split(","))
                .list()
                .stream()
                .map(SysArea::getName)
                .collect(Collectors.toList());
            String liveCityStr = ProvinceCityCountyUtils.getLiveCity(CollUtil.join(liveCity, ""),piInfo.getAddress());
            params.set("liveCity", liveCityStr);
        } else {
            params.set("liveCity", "无");
        }
        File file = fileService.getById(piInfo.getPhotoId());
        if (file != null && new java.io.File(file.getFilePath()).exists()) {
            params.set("photo", Pictures.ofLocal(file.getFilePath()).size(140, 182).create());
        }

        //学历
        List<CvUserEduInfo> userEduInfos = this.cvUserEduInfoService.lambdaQuery()
            .eq(CvUserEduInfo::getResumeId, resume.getId())
            .eq(CvUserEduInfo::getDelFlag, false)
            .orderByDesc(CvUserEduInfo::getStartEduTime)
            .list();
        ArrayList<Dict> eduList = new ArrayList<>();
        boolean notEmptyEdu = CollUtil.isNotEmpty(userEduInfos);
        if (notEmptyEdu) {
            userEduInfos.forEach(e -> {
                String start = DateUtil.format(e.getStartEduTime(), DATE_MONTH_FORMAT);
                String end = DateUtil.format(e.getEndEduTime(), DATE_MONTH_FORMAT);
                String eduRangeTime = start + "-" + end;
                String fullTime = Optional.ofNullable(e.getR2()).map(el ->
                    StrUtil.equals(el, "1") ? "是" : "否"
                ).orElse("无");
                if (1 == lanType) {
                    fullTime = fullTime.replace("是", "YES").replace("否", "NO");
                }

                if (StringUtils.isBlank(e.getR2())) {
                    e.setR2(1 + "");
                }
                String majorName = (StrUtil.equals(e.getMajor(), "无") || e.getEduLevel() == 1 || e.getEduLevel() == 0) ? "" : e.getMajor();
                eduList.add(Dict.of("eduRangeTime", eduRangeTime, "schoolName", e.getSchoolName() ,"major",majorName, "eduLevel",
                        eduLabelUtil.getEduLevel(e.getEduLevel(), resume.getLanType()), "fullTime", fullTime
                        , "r1", eduLabelUtil.geDegree(e.getR1(), resume.getLanType())// 学位 1 学士 2 硕士 3 博士
                        , "r2", fullTime// 是否全日制 1 是 2 不是
                ));
            });

        }

        String firstDegree = "";
        // 最高学历
        if (notEmptyEdu) {
            //2022年4月19日20:55:28 zhf 修复最高学历bug（排序顺序发生了变化）
            CvUserEduInfo cvUserEduInfo = userEduInfos.stream().max(Comparator.comparingInt(CvUserEduInfo::getEduLevel)).get();
            params.put("higEdu", this.eduLabelUtil.getEduLevel(cvUserEduInfo.getEduLevel(), resume.getLanType()));
//            CvUserEduInfo fir = userEduInfos.stream().filter(e -> e.getEduLevel() > 2 && StrUtil.equals(e.getR2(), "1")).sorted(Comparator.comparing(CvUserEduInfo::getStartEduTime).reversed()).findFirst().orElse(null);
            CvUserEduInfo fir = userEduInfos.stream().filter(e -> e.getEduLevel() > 2 && StrUtil.equals(e.getR2(), "1")).sorted(Comparator.comparing(CvUserEduInfo::getStartEduTime)).findFirst().orElse(null);
            if(fir != null){
                //第一学历， 有高中或中专以上就取后的第一个学历
                firstDegree = eduLabelUtil.getEduLevel(fir.getEduLevel());
            }else{
                //如果没有高中或中专以上学历，取现有学历
                firstDegree = eduLabelUtil.getEduLevel(cvUserEduInfo.getEduLevel());
            }
        } else {
            params.put("higEdu", "");
        }
        params.put("firstDegree", firstDegree);

        params.set("edu", eduList);
        //证书
        List<CvCertificate> cvCertificates = this.cvCertificateService.lambdaQuery()
            .eq(CvCertificate::getResumeId, resume.getId())
            .eq(CvCertificate::getDelFlag, false)
            .orderByDesc(CvCertificate::getTime)
            .list();
        ArrayList<Dict> certificates = new ArrayList<>();
        StringBuilder certificatesStr = new StringBuilder();
        if (CollUtil.isNotEmpty(cvCertificates)) {
            cvCertificates.forEach(e -> {
                if (CollUtil.isNotEmpty(certificates)) {
                	certificatesStr.append("\r\n");
				}
                String time = DateUtil.format(e.getTime(), DATE_MONTH_FORMAT);
                certificates.add(Dict.of("name", e.getName(), "time", time, "licenseIssuingUnit", e.getLicenseIssuingUnit()));
                certificatesStr.append(time).append("  ").append(e.getName()).append("  ").append(e.getLicenseIssuingUnit());
            });
        }
        params.set("certificates", certificates);
        //单个cell用
        params.set("certificatesStr", certificatesStr.toString());

        //2022年4月1日11:02:30 zhf  职业特长与技能（专业技能）--->改为了职称
        LambdaQueryWrapper<CvSkills> skillsQuery = new LambdaQueryWrapper<>();
        skillsQuery.eq(CvSkills::getDelFlag, false).eq(CvSkills::getResumeId, resume.getId())
            .orderByDesc(CvSkills::getId);
        StringBuilder skillsInfosStr = new StringBuilder();
        List<CvSkills> cvSkillsInfos = cvSkillsService.list(skillsQuery);
        if (CollUtil.isNotEmpty(cvSkillsInfos)) {
            cvSkillsInfos.forEach(e ->
                skillsInfosStr.append(StrUtil.isNotBlank(skillsInfosStr.toString())?"\r\n":"").append(e.getR1()).append("  ").append(e.getName()).append("  ").append(e.getR2())
            );
        }
        //单个cell用
        params.set("skillsInfosStr", skillsInfosStr.toString());
        //若重要证书和职称都为空
        if(StrUtil.isBlank((String)params.get("certificatesStr")) && StrUtil.isBlank((String)params.get("skillsInfosStr"))){
            params.set("skillsInfosStr", "/");
        }
        //2022年4月1日11:02:30 zhf 添加培训
        List<CvTrain> cvTrainInfos = this.cvTrainService.lambdaQuery()
            .eq(CvTrain::getResumeId, resume.getId())
            .eq(CvTrain::getDelFlag, false).orderByDesc(CvTrain::getStartTime)
            .list();
        StringBuilder trainInfosStr = new StringBuilder();
        ArrayList<Dict> trainInfos = new ArrayList<>();
        if (CollUtil.isNotEmpty(cvTrainInfos)) {
            cvTrainInfos.forEach(e -> {
                String startTime = DateUtil.format(e.getStartTime(), DATE_FORMAT);
                String endTime = DateUtil.format(e.getEndTime(), DATE_FORMAT);
                String time = startTime + " 至 " + endTime;
                if (CollUtil.isNotEmpty(trainInfos)) {
                	trainInfosStr.append("\r\n");
				}
                trainInfos.add(Dict.of("curriculum", e.getCurriculum(), "startTime", startTime, "endTime", endTime, "mechanismName", e.getMechanismName()));

                trainInfosStr.append(time).append("  ").append(e.getCurriculum()).append("  ").append(e.getMechanismName());
            });
        }
        params.set("trainInfos", trainInfos);
        params.set("trainInfosStr", trainInfosStr.toString());
        if(StrUtil.isBlank((String)params.get("trainInfosStr"))){
            params.set("trainInfosStr", "/");
        }
        //工作或实习经历
        List<CvUserWorkInfo> cvUserWorkInfos = this.cvUserWorkInfoService.lambdaQuery()
            .eq(CvUserWorkInfo::getResumeId, resume.getId())
            .eq(CvUserWorkInfo::getDelFlag, false)
            .orderByDesc(CvUserWorkInfo::getWorkStartTime)
            .list();
        List<Dict> works = new ArrayList<>();
        if (CollUtil.isNotEmpty(cvUserWorkInfos)) {
            cvUserWorkInfos.forEach(e -> {
                String start = DateUtil.format(e.getWorkStartTime(), DATE_MONTH_FORMAT);
//                String end = DateUtil.format(e.getWorkEndTime(), DATE_MONTH_FORMAT);
                String end = e.getWorkEndTime().equals(CommonConstant.TO_THIS_DAY) ?
                        CommonConstant.TO_THIS_DAY : DateUtil.format(DateUtils.str2Date(e.getWorkEndTime(), DateUtils.date_sdf.get()), DATE_MONTH_FORMAT);
                String workRangeTime = start + "-" + end;
                String[] position = e.getPositionName().split(",");
                String jobId = ArrayUtil.get(position, -1);
                String jobName=null;
                if(StringUtils.equals(jobId, CommonConstant.OTHER_POSITION)&&StringUtils.isNotBlank(e.getOtherPosition())){
                    jobName = e.getOtherPosition();
                }
                else{
                    jobName = transNameUtil.getTransName("recruitment_position", jobId, "id", "name");//职位
                }
                works.add(Dict.of("workRangeTime", workRangeTime, "companyName", e.getCompanyName(),
                        "positionName", jobName +  ":"  + e.getWorkDescribe()
                        , "r1", e.getR1()//单位类型
                        , "r2", e.getR2()//所属部门
                        , "r3", e.getR3()//单位规模
                        , "r4", e.getR4()//上级职位
                        , "r5", e.getR5()//下属人数
                        , "r6", e.getR6()// 离职原因
                        , "workContent", e.getWorkContent()// 离职原因
                        , "salary", e.getSalary() == null ? "" : e.getSalary() + ""// 离职原因

                    )
                );
            });
        }
        params.set("works", works);

        //项目经历
        List<CvProjectInfo> cvProjectInfos = this.cvProjectInfoService.lambdaQuery()
                .eq(CvProjectInfo::getResumeId, resume.getId())
                .eq(CvProjectInfo::getDelFlag, false)
                .orderByDesc(CvProjectInfo::getStartTime)
                .list();
        List<Dict> projects = new ArrayList<>();
        if (CollUtil.isNotEmpty(cvProjectInfos)) {
            cvProjectInfos.forEach(e -> {
                String start = DateUtil.format(e.getStartTime(), DATE_MONTH_FORMAT);
                String end = DateUtil.format(e.getEndTime(), DATE_MONTH_FORMAT);
                projects.add(Dict.of("projectName", e.getProjectName() //项目名称
                        , "r1", e.getR1()//项目职务
                        , "r2", e.getR2()//所在公司
                        , "r3", StrUtil.isBlank(e.getR3()) ? "/" : e.getR3()//项目职责
                        , "r4", StrUtil.isBlank(e.getR4()) ? "/" : e.getR4()//项目业绩
                        , "startTime", start// 开始时间
                        , "endTime", end // 结束时间
                        , "projectDescribe", e.getProjectDescribe() // 项目描述
                        )
                );
            });
        }
        params.set("projects", projects);

        //家庭成员
        List<CvFamilyMember> cvFamilyMembers = this.cvFamilyMemberService.lambdaQuery()
            .eq(CvFamilyMember::getResumeId, resume.getId())
            .eq(CvFamilyMember::getDelFlag, false).orderByDesc(CvFamilyMember::getId)
            .list();
        List<Dict> family = new ArrayList<>();
        if (CollUtil.isNotEmpty(cvFamilyMembers)) {
            cvFamilyMembers.forEach(e -> {
                String birthday = DateUtil.format(e.getBirthday(), DATE_MONTH_FORMAT);
                String education = StrUtil.isBlank(e.getEducation()) ? "无" : eduLabelUtil.getEduLevel(Convert.toInt(e.getEducation()), resume.getLanType());

                //2022年4月19日20:52:58 修改age ，原因：社招简历也采用生日而非年龄
                String age = e.getAge() + "";
                try {
                    age = DateUtil.ageOfNow(e.getBirthday()) + "";
                } catch (Exception e2) {
                    e2.printStackTrace();
                }

                family.add(Dict.of("name", e.getName(), "appellation", e.getAppellation(), "education", education,
                    "politics", e.getPolitics(),
                    "birthday", birthday, "company", e.getCompany(), "phone", e.getPhone(), "position", e.getPosition()
                    , "age", age
                    , "remark", e.getRemark()
                ));
            });
        }
        if (1 == resume.getResumeType()) {//社招
            if(StrUtil.isBlank(resume.getOtherSituations()) || "无".equals(resume.getOtherSituations().trim())){
                params.set("otherSituations_no",  "无");
            }else{
                params.set("otherSituations", resume.getOtherSituations());
            }
        }else{
            if(StrUtil.isBlank(resume.getOtherSituations()) || "无".equals(resume.getOtherSituations().trim())){
                params.set("otherSituations",  "无");
            }else{
                params.set("otherSituations",  resume.getOtherSituations());
            }
        }
        params.set("family", family);
        params.set("majorResearchDirection", StrUtil.isBlank(resume.getMajorResearchDirection()) ? "/" : resume.getMajorResearchDirection());
        params.set("selfEvaluation", StrUtil.isBlank(resume.getSelfEvaluation()) ? "无" : resume.getSelfEvaluation());
        if(StrUtil.isBlank(resume.getOtherSituations()) || "无".equals(resume.getOtherSituations().trim())){
            params.set("otherSituations_no",  "无");
        }else{
            params.set("otherSituations", resume.getOtherSituations());
        }
        params.set("sfxy", StrUtil.isBlank(resume.getTripartiteAgreement()) ? "无" : resume.getTripartiteAgreement());
        String path = "/private/resume/" + DateUtil.format(resume.getCreateTime(), "yyyy/MM/");
        HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();

        Configure config = Configure.builder()
            .bind("edu", policy)
            .bind("certificates", policy)
            .bind("works", policy)
            .bind("projects", policy)
            .bind("family", policy)
            .build();
        ClassPathResource resource = null;
        String suffixName = null;
        log.info("=======resume.getResumeType()校招还是社招=======" + resume.getResumeType());
        log.info("=======lanType语种=======" + lanType);
        if (1 == resume.getResumeType()) {
            if (1 == lanType) {
                //lanType 语种  0 中文  1英文
                resource = new ClassPathResource("resume/doc/resume_en.docx");
                suffixName = "_在线英文社招简历.docx";
            } else {
                resource = new ClassPathResource("resume/doc/resume_zh.docx");
                suffixName = "_在线社招简历.docx";
            }
        } else {
            if (1 == lanType) {
                //lanType 语种  0 中文  1英文
                resource = new ClassPathResource("resume/doc/resume_school_en.docx");
                suffixName = "_在线英文校招简历.docx";
            } else {
                resource = new ClassPathResource("resume/doc/resume_school_zh.docx");
                suffixName = "_在线校招简历.docx";
            }
        }

        XWPFTemplate template = XWPFTemplate.compile(resource.getInputStream(), config).render(
            params
        );
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        template.write(byteArrayOutputStream);
        path = sysBaseAPI.uploadToLocal(byteArrayOutputStream.toByteArray(), path, piInfo.getName() + "_" + piInfo.getPhone() + suffixName, false).toString();

        log.info("word============> 生成位置={}", path);

        IoUtil.close(byteArrayOutputStream);
        if (1 == lanType) {
            resume.setWordPathEn(path);
        } else {
            resume.setWordPath(path);
        }
        cvResumeService.updateById(resume);
        return path;
    }

}
